Skip to content

Feat/agentic explicit gating#33

Open
1amKhush wants to merge 12 commits into
ContextVM:masterfrom
1amKhush:feat/agentic-explicit-gating
Open

Feat/agentic explicit gating#33
1amKhush wants to merge 12 commits into
ContextVM:masterfrom
1amKhush:feat/agentic-explicit-gating

Conversation

@1amKhush

@1amKhush 1amKhush commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Description

This PR implements the end-to-end integration of the CEP-8 explicit gating payment lifecycle within the ContextVM web client.

By migrating away from the legacy transparent notification-based flow, we enable autonomous agent handling of payment requirements. When an MCP server demands payment, the LLM now natively receives the -32042 Payment Required or -32043 Payment Pending JSON-RPC errors as structured context, allowing it to inform the user, wait for payment confirmation, or autonomously retry.

Implements #32

Architectural Changes & Key Features

  • Lossless Error Propagation: Intercepts -32042 and -32043 JSON-RPC errors at the transport layer, losslessly serializing them into ExplicitGatingError payloads that surface as payment_required statuses inside LLM ToolCallData.
  • PMI-Agnostic Client Negotiation: Removes hardcoded payment handlers (e.g., UiOnlyPaymentHandler) in favor of dynamic CEP-8 "catch-all" behavior, allowing the server to dictate accepted Payment Method Identifiers (PMIs).
  • Isolated Payment UI (PaymentErrorCard): Introduces a robust, standalone Svelte component to render single or multi-option payment invoices (with QR codes and copy actions) entirely uncoupled from the legacy PaymentStatusPanel state.
  • Agentic Orchestration: Updates AgentOrchestrator to catch explicit gating errors, pausing the tool execution loop and feeding the invoice context directly back to the active model.
  • Server Dashboard Tooling: Adds a mode-toggle switch on the public server page ([pubkey]/+page.svelte) that initiates a clean transport reconnect cycle to test tools in both transparent and explicit_gating modes.

Testing Performed

  • Regression Tested: Legacy transparent payment mode continues to function properly when explicit gating is not negotiated.
  • Component Rendering: PaymentErrorCard successfully iterates and renders multiple payment methods with distinct, non-leaking tab states for QR/invoice views.
  • Unit Testing: bun test passes, including new orchestrator unit tests validating the -32042 extraction, serialization, and status-marking flows without timeout bottlenecks.
  • Type Safety: svelte-check reports 0 errors across the entire codebase.

Copilot AI review requested due to automatic review settings July 3, 2026 07:50
@vercel

vercel Bot commented Jul 3, 2026

Copy link
Copy Markdown

@1amKhush is attempting to deploy a commit to the ContextVM's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds client-side support for CEP-8 “explicit gating” payments by propagating -32042/-32043 JSON-RPC errors through the MCP tool execution path, surfacing them as a first-class tool-call status (payment_required) and rendering invoices directly in the UI (including a new server-page toggle to request explicit_gating vs transparent mode).

Changes:

  • Introduces explicit-gating error extraction/serialization utilities and wires them into AgentOrchestrator tool execution to mark tool calls as payment_required.
  • Adds PaymentErrorCard and integrates it into chat/tool UI and server capability forms to render invoices/QRs when gating errors occur.
  • Adds per-connection payment interaction mode selection and reconnect support in McpClientService, plus a toggle UI on the public server page.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/routes/s/[pubkey]/+page.svelte Adds a payment-mode toggle (transparent vs explicit_gating) and reconnect flow on the server page.
src/lib/types/chat-types.ts Extends ToolCallData with payment_required status and an optional paymentError payload.
src/lib/services/payments/payment-errors.ts Adds CEP-8 error codes plus helpers to extract/serialize explicit gating errors.
src/lib/services/payments/payment-errors.test.ts Adds unit tests for explicit gating error extraction and serialization.
src/lib/services/mcpClient.svelte.ts Adds connection mode tracking and reconnect-with-mode; updates payments middleware configuration.
src/lib/services/agent-orchestrator.ts Catches CEP-8 errors during tool calls and marks tool calls as payment_required with serialized payload.
src/lib/services/agent-orchestrator.test.ts Adds orchestrator tests for the new payment_required status + lossless serialization.
src/lib/components/ToolCallForm.svelte Displays PaymentErrorCard when tool invocation fails with explicit gating errors.
src/lib/components/ResourceReadForm.svelte Displays PaymentErrorCard when resource reads hit explicit gating errors.
src/lib/components/PromptGetForm.svelte Displays PaymentErrorCard when prompt fetch hits explicit gating errors.
src/lib/components/chat/ToolCallCard.svelte Updates tool-call status UI to include payment_required and renders PaymentErrorCard for tool calls.
src/lib/components/chat/PaymentErrorCard.svelte New UI component to render invoice/QR/instructions from explicit gating errors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/services/mcpClient.svelte.ts Outdated
Comment thread src/lib/components/chat/PaymentErrorCard.svelte Outdated
Comment thread src/lib/components/chat/PaymentErrorCard.svelte Outdated
Comment thread src/lib/components/chat/PaymentErrorCard.svelte Outdated
Comment thread src/lib/components/chat/PaymentErrorCard.svelte Outdated
Comment thread src/lib/services/agent-orchestrator.test.ts Outdated
Comment thread src/lib/services/agent-orchestrator.test.ts Outdated
Comment thread src/lib/services/agent-orchestrator.test.ts Outdated
- mcpClient: Add transparent-mode payment_required notification handler
- PaymentErrorCard: Fix retryAfter truthiness check and literal tab IDs
- agent-orchestrator.test: Replace hardcoded delays with polling
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
contextvm-site Ready Ready Preview, Comment Jul 7, 2026 4:45pm

- chat: render transparent-mode payments via the existing
  PaymentStatusPanel so priced tools no longer hang silently; thread
  serverPubkey onto ToolCallData from the orchestrator
- orchestrator: remove the max-tool-rounds guard (TODO) — run until the
  model stops calling tools or the user aborts; drop the now-dead
  maxToolRounds/stoppedByMaxRounds plumbing
- server page: make effectivePaymentMode reactive to connectionState so
  the "Effective:" caption and mode-mismatch warning are correct after a
  reconnect (client-side display fix; orthogonal to the SDK toggle bug)
- cleanup: delete dead UiOnlyPaymentHandler (no importers)
SDK 0.13.7 adds mid-session payment_interaction renegotiation, which
resolves the toggle-latching half of issue ContextVM#1: the server no longer
latches a pubkey to explicit_gating for the session, and the client now
advertises payment_interaction=transparent as a real downgrade intent.
Combined with the client-side effectivePaymentMode reactivity fix, the
server-page mode switch should now toggle behavior end-to-end.

- createTransport: drop the conditional-spread + cast — withClientPayments
  now honors any truthy mode, so transparent is no longer a silent no-op
@ContextVM-org

Copy link
Copy Markdown
Contributor

Great progress. I fixed a couple of issues. Something still remaining is the ui of the toggle. Please review it and just render under a collapsible and if the server have at least one paid tool.

@1amKhush

1amKhush commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@ContextVM-org implemented the UI refinement for the toggle (conditionally rendered only if paid capabilities exist, tucked into a collapsible).

Did a audit on the logic and it aligns well with the docs as well.

Two minor observations I noted during the audit (neither are bugs, just things to keep in mind):

  1. Transparent mode UI correlation: In ToolCallCard.svelte, the transparent payment panel is fetched via paymentNotificationsService.getLatestForServer(toolCall.serverPubkey). This returns the most recent payment notification for that server rather than per-request. If two tools on the same server are in-flight simultaneously, both would technically show the same payment panel. This is a pre-existing limitation inherited from the old PaymentStatusPanel (the MCP SDK doesn't expose the request event ID out of callTool), so it's not a regression, just a quirk of transparent mode.
  2. Toggle visibility state: To determine if the toggle should be shown, the page parses NIP-89 announcement event tags (toolsAnnouncementTags). If a server adds pricing after the announcement was cached (i.e. at runtime in the tools/list response), the toggle won't appear until the announcement query is refreshed. This feels acceptable since the announcement is the discovery-time source of truth, and individual tools still render their runtime price tags correctly in the UI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants